package interrupt;


public class ALU extends Register {
    private boolean FLAG_CARRY;   //��λ
    private boolean FLAG_ZERO;    //Ϊ��
    @SuppressWarnings("unused")
	private boolean FLAG_OVER;    //���
    private boolean FLAG_SIGN;    //Ϊ��
    public ALU(){
        super();
        this.init();
    }

    public void init(){
        this.FLAG_CARRY = false;
        this.FLAG_OVER = false;
        this.FLAG_SIGN = false;
        this.FLAG_ZERO = false;
    }

    public  synchronized  boolean getC(){
        return this.FLAG_CARRY;
    }

    public synchronized  boolean getZ(){
        return this.FLAG_ZERO;
    }

    public synchronized  boolean getS(){
        return this.FLAG_SIGN;
    }
    public synchronized  void setC(boolean CARRY){
        this.FLAG_CARRY = CARRY;
    }

    public  synchronized void setZ(boolean ZERO){
        this.FLAG_ZERO = ZERO;
    }

    public synchronized  void setS(boolean SIGN){
        this.FLAG_SIGN = SIGN;
    }

    public synchronized  void ADD(final short num){
        init();
        short result = this.getReg();
        byte count;
        StringBuilder a = Tools.getBin(result);
        StringBuilder b = Tools.getBin(num);
        for(int i = 15; i >= 0; i--) {
            count = 0;
            //ͳ�Ƶ�iλ�������ͽ�λ�����
            if(FLAG_CARRY) count++;
            if(a.charAt(i) == '1') count++;
            if(b.charAt(i) == '1') count++;
            switch(count) {
                case 0:{
                    a.replace(i, i+1, "0");
                    this.FLAG_CARRY = false;
                    break;
                }
                case 1:{
                    a.replace(i, i+1, "1");
                    this.FLAG_CARRY = false;
                    break;
                }
                case 2:{
                    a.replace(i, i+1, "0");
                    this.FLAG_CARRY = true;
                    break;
                }
                case 3:{
                    a.replace(i, i+1, "1");
                    this.FLAG_CARRY = true;
                    break;
                }
            }
        }
        if(a.charAt(0) == '1') FLAG_SIGN = true;//Sλ
        this.setReg(Integer.valueOf(a.toString(), 2).shortValue());
        for(int i = 15; i >= 0; i--) {
            if(a.charAt(i) == 49) {
                return;
            }
        }

        //result = 0;

        FLAG_OVER = true;
        FLAG_ZERO = true;
        //this.setReg(result);
    }

    public synchronized  void SUB(short num){
        num = (short) -num;
        this.ADD(num);
    }

    public synchronized  void AND(final short num){
        short reg = this.getReg();
        reg = (short) (reg & (short)num);
        this.setReg(reg);
    }

    public synchronized  void OR(final short num){
        short reg = this.getReg();
        reg = (short) (reg | (short)num);
        this.setReg(reg);
    }

    public synchronized  void XOR(final short num){
        short reg = this.getReg();
        reg = (short) (reg ^ (short)num);
        this.setReg(reg);
    }

    public  synchronized void MOV_L(boolean loop){
        short reg = this.getReg();
        boolean temp = this.FLAG_CARRY;
        this.FLAG_CARRY = reg < 0;
        reg = (short) (reg << 1);
        if(loop && temp)
            reg += 1;
        this.setReg(reg);
    }

    public synchronized  void MOV_R(boolean loop){
        short reg = this.getReg();
        boolean temp = this.FLAG_CARRY;
        this.FLAG_CARRY = reg%2 == 1;
        reg = (short) (reg >>> 1);
        if(loop && temp){
            reg = Tools.reverse(reg);
            reg++;
            reg = Tools.reverse(reg);
        }
        this.setReg(reg);
    }
}
